home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / mgr / sparcmgr / demo2.zoo / demo / ex / ex_vwind.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-04-24  |  8.1 KB  |  469 lines

  1. /*
  2.  * Copyright (c) 1980 Regents of the University of California.
  3.  * All rights reserved.  The Berkeley software License Agreement
  4.  * specifies the terms and conditions for redistribution.
  5.  */
  6.  
  7. #ifndef lint
  8. static char *sccsid = "@(#)ex_vwind.c    7.4 (Berkeley) 3/9/87; 1.2 (Bellcore)    87/04/24";
  9. #endif not lint
  10.  
  11. #include "ex.h"
  12. #include "ex_tty.h"
  13. #include "ex_vis.h"
  14.  
  15. /*
  16.  * Routines to adjust the window, showing specified lines
  17.  * in certain positions on the screen, and scrolling in both
  18.  * directions.  Code here is very dependent on mode (open versus visual).
  19.  */
  20.  
  21. /*
  22.  * Move in a nonlocal way to line addr.
  23.  * If it isn't on screen put it in specified context.
  24.  * New position for cursor is curs.
  25.  * Like most routines here, we vsave().
  26.  */
  27. vmoveto(addr, curs, context)
  28.     register line *addr;
  29.     char *curs;
  30.     char context;
  31. {
  32.  
  33.     markit(addr);
  34.     vsave();
  35.     vjumpto(addr, curs, context);
  36. }
  37.  
  38. /*
  39.  * Vjumpto is like vmoveto, but doesn't mark previous
  40.  * context or save linebuf as current line.
  41.  */
  42. vjumpto(addr, curs, context)
  43.     register line *addr;
  44.     char *curs;
  45.     char context;
  46. {
  47.  
  48.     ignore(noteit(0));
  49.     if (context != 0)
  50.         vcontext(addr, context);
  51.     else
  52.         vshow(addr, NOLINE);
  53.     ignore(noteit(1));
  54.     vnline(curs);
  55. }
  56.  
  57. /*
  58.  * Go up or down cnt (negative is up) to new position curs.
  59.  */
  60. vupdown(cnt, curs)
  61.     register int cnt;
  62.     char *curs;
  63. {
  64.  
  65.     if (cnt > 0)
  66.         vdown(cnt, 0, 0);
  67.     else if (cnt < 0)
  68.         vup(-cnt, 0, 0);
  69.     if (vcnt == 0)
  70.         vrepaint(curs);
  71.     else
  72.         vnline(curs);
  73. }
  74.  
  75. /*
  76.  * Go up cnt lines, afterwards preferring to be ind
  77.  * logical lines from the top of the screen.
  78.  * If scroll, then we MUST use a scroll.
  79.  * Otherwise clear and redraw if motion is far.
  80.  */
  81. vup(cnt, ind, scroll)
  82.     register int cnt, ind;
  83.     bool scroll;
  84. {
  85.     register int i, tot;
  86.  
  87.     if (dot == one) {
  88.         beep();
  89.         return;
  90.     }
  91.     vsave();
  92.     i = lineDOT() - 1;
  93.     if (cnt > i) {
  94.         ind -= cnt - i;
  95.         if (ind < 0)
  96.             ind = 0;
  97.         cnt = i;
  98.     }
  99.     if (!scroll && cnt <= vcline) {
  100.         vshow(dot - cnt, NOLINE);
  101.         return;
  102.     }
  103.     cnt -= vcline, dot -= vcline, vcline = 0;
  104.     if (hold & HOLDWIG)
  105.         goto contxt;
  106.     if (state == VISUAL && !AL && !SR &&
  107.         cnt <= WTOP - ex_ZERO && vfit(dot - cnt, cnt) <= WTOP - ex_ZERO)
  108.         goto okr;
  109.     tot = WECHO - ex_ZERO;
  110.     if (state != VISUAL || (!AL && !SR) || (!scroll && (cnt > tot || vfit(dot - cnt, cnt) > tot / 3 + 1))) {
  111.         if (ind > basWLINES / 2)
  112.             ind = basWLINES / 3;
  113. contxt:
  114.         vcontext(dot + ind - cnt, '.');
  115.         return;
  116.     }
  117. okr:
  118.     vrollR(cnt);
  119.     if (scroll) {
  120.         vcline += ind, dot += ind;
  121.         if (vcline >= vcnt)
  122.             dot -= vcline - vcnt + 1, vcline = vcnt - 1;
  123.         getDOT();
  124.     }
  125. }
  126.  
  127. /*
  128.  * Like vup, but scrolling down.
  129.  */
  130. vdown(cnt, ind, scroll)
  131.     register int cnt, ind;
  132.     bool scroll;
  133. {
  134.     register int i, tot;
  135.  
  136.     if (dot == dol) {
  137.         beep();
  138.         return;
  139.     }
  140.     vsave();
  141.     i = dol - dot;
  142.     if (cnt > i) {
  143.         ind -= cnt - i;
  144.         if (ind < 0)
  145.             ind = 0;
  146.         cnt = i;
  147.     }
  148.     i = vcnt - vcline - 1;
  149.     if (!scroll && cnt <= i) {
  150.         vshow(dot + cnt, NOLINE);
  151.         return;
  152.     }
  153.     cnt -= i, dot += i, vcline += i;
  154.     if (hold & HOLDWIG)
  155.         goto dcontxt;
  156.     if (!scroll) {
  157.         tot = WECHO - ex_ZERO;
  158.         if (state != VISUAL || cnt - tot > 0 || vfit(dot, cnt) > tot / 3 + 1) {
  159. dcontxt:
  160.             vcontext(dot + cnt, '.');
  161.             return;
  162.         }
  163.     }
  164.     if (cnt > 0)
  165.         vroll(cnt);
  166.     if (state == VISUAL && scroll) {
  167.         vcline -= ind, dot -= ind;
  168.         if (vcline < 0)
  169.             dot -= vcline, vcline = 0;
  170.         getDOT();
  171.     }
  172. }
  173.  
  174. /*
  175.  * Show line addr in context where on the screen.
  176.  * Work here is in determining new top line implied by
  177.  * this placement of line addr, since we always draw from the top.
  178.  */
  179. vcontext(addr, where)
  180.     register line *addr;
  181.     char where;
  182. {
  183.     register line *top;
  184.  
  185.     getline(*addr);
  186.     if (state != VISUAL)
  187.         top = addr;
  188.     else switch (where) {
  189.  
  190.     case '^':
  191.         addr = vback(addr, basWLINES - vdepth());
  192.         getline(*addr);
  193.         /* fall into ... */
  194.  
  195.     case '-':
  196.         top = vback(addr, basWLINES - vdepth());
  197.         getline(*addr);
  198.         break;
  199.  
  200.     case '.':
  201.         top = vback(addr, basWLINES / 2 - vdepth());
  202.         getline(*addr);
  203.         break;
  204.  
  205.     default:
  206.         top = addr;
  207.         break;
  208.     }
  209.     if (state == ONEOPEN && LINE(0) == WBOT)
  210.         vup1();
  211.     vcnt = vcline = 0;
  212.     vclean();
  213.     if (state == CRTOPEN)
  214.         vup1();
  215.     vshow(addr, top);
  216. }
  217.  
  218. /*
  219.  * Get a clean line.  If we are in a hard open
  220.  * we may be able to reuse the line we are on
  221.  * if it is blank.  This is a real win.
  222.  */
  223. vclean()
  224. {
  225.  
  226.     if (state != VISUAL && state != CRTOPEN) {
  227.         destcol = 0;
  228.         if (!ateopr())
  229.             vup1();
  230.         vcnt = 0;
  231.     }
  232. }
  233.  
  234. /*
  235.  * Show line addr with the specified top line on the screen.
  236.  * Top may be 0; in this case have vcontext compute the top
  237.  * (and call us recursively).  Eventually, we clear the screen
  238.  * (or its open mode equivalent) and redraw.
  239.  */
  240. vshow(addr, top)
  241.     line *addr, *top;
  242. {
  243. #ifndef CBREAK
  244.     register bool fried = 0;
  245. #endif
  246.     register int cnt = addr - dot;
  247.     register int i = vcline + cnt;
  248.     short oldhold = hold;
  249.  
  250.     if (state != HARDOPEN && state != ONEOPEN && i >= 0 && i < vcnt) {
  251.         dot = addr;
  252.         getDOT();
  253.         vcline = i;
  254.         return;
  255.     }
  256.     if (state != VISUAL) {
  257.         dot = addr;
  258.         vopen(dot, WBOT);
  259.         return;
  260.     }
  261.     if (top == 0) {
  262.         vcontext(addr, '.');
  263.         return;
  264.     }
  265.     dot = top;
  266. #ifndef CBREAK
  267.     if (vcookit(2))
  268.         fried++, vcook();
  269. #endif
  270.     oldhold = hold;
  271.     hold |= HOLDAT;
  272.     vclear();
  273.     vreset(0);
  274.     vredraw(WTOP);
  275.     /* error if vcline >= vcnt ! */
  276.     vcline = addr - top;
  277.     dot = addr;
  278.     getDOT();
  279.     hold = oldhold;
  280.     vsync(LASTLINE);
  281. #ifndef CBREAK
  282.     if (fried)
  283.         flusho(), vraw();
  284. #endif
  285. }
  286.  
  287. /*
  288.  * reset the state.
  289.  * If inecho then leave us at the beginning of the echo
  290.  * area;  we are called this way in the middle of a :e escape
  291.  * from visual, e.g.
  292.  */
  293. vreset(inecho)
  294.     bool inecho;
  295. {
  296.  
  297.     vcnt = vcline = 0;
  298.     WTOP = basWTOP;
  299.     WLINES = basWLINES;
  300.     if (inecho)
  301.         splitw = 1, vgoto(WECHO, 0);
  302. }
  303.  
  304. /*
  305.  * Starting from which line preceding tp uses almost (but not more
  306.  * than) cnt physical lines?
  307.  */
  308. line *
  309. vback(tp, cnt)
  310.     register int cnt;
  311.     register line *tp;
  312. {
  313.     register int d;
  314.  
  315.     if (cnt > 0)
  316.         for (; tp > one; tp--) {
  317.             getline(tp[-1]);
  318.             d = vdepth();
  319.             if (d > cnt)
  320.                 break;
  321.             cnt -= d;
  322.         }
  323.     return (tp);
  324. }
  325.  
  326. /*
  327.  * How much scrolling will it take to roll cnt lines starting at tp?
  328.  */
  329. vfit(tp, cnt)
  330.     register line *tp;
  331.     int cnt;
  332. {
  333.     register int j;
  334.  
  335.     j = 0;
  336.     while (cnt > 0) {
  337.         cnt--;
  338.         getline(tp[cnt]);
  339.         j += vdepth();
  340.     }
  341.     if (tp > dot)
  342.         j -= WBOT - LASTLINE;
  343.     return (j);
  344. }
  345.  
  346. /*
  347.  * Roll cnt lines onto the screen.
  348.  */
  349. vroll(cnt)
  350.     register int cnt;
  351. {
  352. #ifndef CBREAK
  353.     register bool fried = 0;
  354. #endif
  355.     short oldhold = hold;
  356.  
  357. #ifdef ADEBUG
  358.     if (trace)
  359.         tfixnl(), fprintf(trace, "vroll(%d)\n", cnt);
  360. #endif
  361.     if (state != VISUAL)
  362.         hold |= HOLDAT|HOLDROL;
  363.     if (WBOT == WECHO) {
  364.         vcnt = 0;
  365.         if (state == ONEOPEN)
  366.             vup1();
  367.     }
  368. #ifndef CBREAK
  369.     if (vcookit(cnt))
  370.         fried++, vcook();
  371. #endif
  372.     for (; cnt > 0 && Peek_key != ATTN; cnt--) {
  373.         dot++, vcline++;
  374.         vopen(dot, LASTLINE);
  375.         vscrap();
  376.     }
  377.     hold = oldhold;
  378.     if (state == HARDOPEN)
  379.         sethard();
  380.     vsyncCL();
  381. #ifndef CBREAK
  382.     if (fried)
  383.         flusho(), vraw();
  384. #endif
  385. }
  386.  
  387. /*
  388.  * Roll backwards (scroll up).
  389.  */
  390. vrollR(cnt)
  391.     register int cnt;
  392. {
  393.     short oldhold = hold;
  394.  
  395. #ifdef ADEBUG
  396.     if (trace)
  397.         tfixnl(), fprintf(trace, "vrollR(%d), dot=%d\n", cnt, lineDOT());
  398. #endif
  399. #ifndef CBREAK
  400.     if (vcookit(cnt))
  401.         fried++, vcook();
  402. #endif
  403.     if (WBOT == WECHO)
  404.         vcnt = 0;
  405.     heldech = 0;
  406.     hold |= HOLDAT|HOLDECH;
  407.     for (; cnt > 0 && Peek_key != ATTN; cnt--) {
  408.         dot--;
  409.         vopen(dot, WTOP);
  410.         vscrap();
  411.     }
  412.     hold = oldhold;
  413.     if (heldech)
  414.         vclrech(0);
  415.     vsync(LINE(vcnt-1));
  416. #ifndef CBREAK
  417.     if (fried)
  418.         flusho(), vraw();
  419. #endif
  420. }
  421.  
  422. /*
  423.  * Go into cooked mode (allow interrupts) during
  424.  * a scroll if we are at less than 1200 baud and not
  425.  * a 'vi' command, of if we are in a 'vi' command and the
  426.  * scroll is more than 2 full screens.
  427.  *
  428.  * BUG:        An interrupt during a scroll in this way
  429.  *        dumps to command mode.
  430.  */
  431. vcookit(cnt)
  432.     register int cnt;
  433. {
  434.  
  435.     return (cnt > 1 && (ospeed < B1200 && !initev || cnt > LINES * 2));
  436. }
  437.  
  438. /*
  439.  * Determine displayed depth of current line.
  440.  */
  441. vdepth()
  442. {
  443.     register int d;
  444.  
  445.     d = (column(NOSTR) + WCOLS - 1 + (Put_char == listchar) + IN) / WCOLS;
  446. #ifdef ADEBUG
  447.     if (trace)
  448.         tfixnl(), fprintf(trace, "vdepth returns %d\n", d == 0 ? 1 : d);
  449. #endif
  450.     return (d == 0 ? 1 : d);
  451. }
  452.  
  453. /*
  454.  * Move onto a new line, with cursor at position curs.
  455.  */
  456. vnline(curs)
  457.     char *curs;
  458. {
  459.  
  460.     if (curs)
  461.         wcursor = curs;
  462.     else if (vmoving)
  463.         wcursor = vfindcol(vmovcol);
  464.     else
  465.         wcursor = vskipwh(linebuf);
  466.     cursor = linebuf;
  467.     vmove();
  468. }
  469.